<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>商品目录管理</title>

    <style>
        .container { display: flex; gap: 20px; height: calc(100vh - 40px); }
        .tree-container { flex: 0 0 30%; background: #f5f7fa; padding: 20px; border-radius: 8px; }
        .operation-panel { flex: 1; display: flex; flex-direction: column; gap: 15px; }
        .el-tree { height: 100%; }
        .card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        .action-bar { display: flex; justify-content: space-between; align-items: center; }
        .breadcrumb { margin-bottom: 15px; color: #666; }
        .form-container { flex: 1; overflow-y: auto; }
        .image-preview {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 9999;
        }

        .preview-content {
            position: relative;
            max-width: 80%;
            max-height: 80%;
        }

        .preview-content img {
            max-width: 100%;
            max-height: 100%;
            object-fit: contain;
        }

        .close-btn {
            position: absolute;
            top: 10px;
            right: 10px;
            color: white;
            font-size: 24px;
            cursor: pointer;
        }
    </style>

</head>
<body>
<div id="app" style="padding: 20px">
    <el-container class="container">
        <!-- 左侧分类树 -->
        <div class="tree-container">
            <div class="action-bar">
                <h3>分类目录</h3>
                <el-input placeholder="搜索分类" v-model="searchKey" prefix-icon="el-icon-search"></el-input>
            </div>

            <el-tree
                    :data="filteredCategoryTree"
                    :props="treeProps"
                    node-key="categoryId"
                    :expand-on-click-node="true"
                    @node-click="handleNodeClick"
                    :draggable="true"
                    @node-drop="handleNodeDrop">
                <span class="custom-tree-node" slot-scope="{ node, data }">
                    <span :class="{'el-tree-node__label--current': currentNode && currentNode.categoryId === data.categoryId}">
                        {{ data.categoryName }}
                    </span>
                </span>
            </el-tree>

        </div>

        <!-- 右侧操作面板 -->
        <div class="operation-panel">
            <div class="card action-bar">
                <div>
                    <el-breadcrumb separator="/">
                        <el-breadcrumb-item v-for="(item, index) in breadcrumbList" :key="index">{{ item }}</el-breadcrumb-item>
                    </el-breadcrumb>
                </div>
                <div>
                    <el-button type="primary" @click="openAddDialog">新增子分类</el-button>
                    <el-button v-if="currentNode" type="danger" @click="deleteCategory(currentNode.categoryId)">删除</el-button>
                </div>
            </div>

            <div class="card form-container">
                <el-form :model="form" :rules="rules" ref="form" label-width="80px" v-show="showForm">
                    <el-form-item label="分类名称">
                        <el-input v-model="form.categoryName" placeholder="请输入分类名称"></el-input>
                    </el-form-item>

                    <el-form-item label="父级分类">
                        <div class="input-with-tree">
                            <el-input
                                    v-model="form.parentName"
                                    :placeholder="dialogType === 'add' ? '一级分类选根目录' : '请选择父级分类'"
                                    :disabled="dialogDisabled"
                                    @click="showTreeDialog = true">
                            </el-input>
                        </div>
                    </el-form-item>

                    <el-form-item label="排序序号">
                        <el-input-number
                                v-model="form.sortOrder"
                                :min="0"
                                placeholder="请输入排序序号（数值越小越靠前）"></el-input-number>
                    </el-form-item>

                    <!-- 图片上传组件 -->
                    <el-form-item label="图片">
                        <el-upload
                                class="upload-demo"
                                :action="ossUploadUrl"
                        :auto-upload="true"
                        :on-change="handleImageChange"
                        :on-success="handleUploadSuccess"
                        :before-upload="beforeUpload"
                        accept="image/*"
                        :show-file-list="false">
                        <el-button slot="trigger" type="primary">选择图片</el-button>
                        </el-upload>
                        <!-- 图片预览与删除 -->
                        <div v-if="form.imageUrl" class="image-preview-container">
                            <img
                                    :src="form.imageUrl"
                                    style="max-width: 100px; max-height: 100px; margin-top: 10px;"
                                    @click="openImagePreview(form.imageUrl)"> <!-- 点击打开预览 -->
                            <el-button
                                    type="danger"
                                    @click="deleteImage(form.imageUrl)"> <!-- 调用删除接口 -->
                                删除图片
                            </el-button>
                        </div>

                        <!-- 图片预览层（取消注释并绑定数据） -->
                        <div class="image-preview" v-show="isPreviewVisible">
                            <div class="preview-content">
                                <img :src="previewUrl" alt="预览图片">
                                <span class="close-btn" @click="closeImagePreview">×</span>
                            </div>
                        </div>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="handleSubmit">提交</el-button>
                    </el-form-item>
                </el-form>
            </div>
        </div>
    </el-container>
</div>

<script src="js/vue.js"></script>
<script src="js/element-ui/lib/index.js"></script>
<script src="js/axios-0.18.0.js"></script>
<link rel="stylesheet" href="js/element-ui/lib/theme-chalk/index.css">

<script>
    new Vue({
        el: '#app',
        data() {
            return {
                searchKey: '',
                currentNode: null,
                breadcrumbList: [],
                showForm: false,
                categoryTree: [],
                dialogType: '',
                imageFile: null,
                showTreeDialog: false,
                isPreviewVisible: false, // 控制预览层显示/隐藏
                previewUrl: '',// 预览图片的 URL
                form: {
                    categoryId: '',
                    categoryName: '',
                    parentId: '',
                    sortOrder: 0,
                    imageUrl: '',
                    parentName: '根目录'
                },
                rules: {
                    categoryName: [{ required: true, message: '分类名称必填', trigger: 'blur' }],
                    sortOrder: [{ type: 'number', message: '排序序号需为数字', trigger: 'blur' }],
                    parentId: [{ required: true, message: '请选择父级分类', trigger: 'change' }]
                },
                treeProps: {
                    label: 'categoryName',
                    children: 'children'
                },
                treeSelectProps: {
                    label: 'categoryName',
                    children: 'children',
                    nodeKey: 'categoryId'
                },
                parentTreeData: [],
                ossUploadUrl: 'http://localhost:8001/oss/category/upload/',// OSS上传接口
                currentImageFileName: ''
            };
        },
        computed: {
            filteredCategoryTree() {
                if (!this.searchKey) return this.categoryTree;
                return this.categoryTree.filter(node =>
                    this.filterNode(node, this.searchKey)
                );
            },
            dialogDisabled() {
                return true;
            }
        },
        created() {
            this.loadCategoryTree();
            this.loadParentTreeData();
        },
        methods: {
            beforeUpload(file) {
                const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
                const isLt2M = file.size / 1024 / 1024 < 2;

                if (!isJPG) {
                    this.$message.error('上传图片只能是 JPG 或 PNG 格式!');
                }
                if (!isLt2M) {
                    this.$message.error('上传图片大小不能超过 2MB!');
                }
                return isJPG && isLt2M;
            },
            // 上传成功处理
            handleUploadSuccess(response, file, fileList) {
                if (response.code === 20011) { // 假设后端成功码为 Code.SAVE_OK（20011）
                    this.form.imageUrl = response.data; // 直接使用后端返回的 URL
                    this.currentImageFileName = response.data.split('/').pop(); // 提取文件名（用于删除）
                    this.$message.success('图片上传成功');
                } else {
                    this.$message.error('图片上传失败');
                }
            },
            // 打开图片预览
            openImagePreview(url) {
                this.previewUrl = url;
                this.isPreviewVisible = true;
            },
            // 关闭图片预览
            closeImagePreview() {
                this.isPreviewVisible = false;
            },
            // 删除图片（调用后端接口）
            deleteImage(url) {
                this.currentImageFileName =url.split('/').pop();
                if (!this.currentImageFileName || !this.form.categoryId) return; // 确保有 categoryId

                this.$confirm('确认删除图片？', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    // 传递 categoryId 参数
                    axios.delete(`/category/deleteimage/${this.currentImageFileName}`, {
                        params: { categoryId: this.form.categoryId }
                    })
                        .then(res => {
                            if (res.data.code === 20021) {
                                this.$message.success(res.data.msg);
                                this.form.imageUrl = '';
                                this.currentImageFileName = '';
                            } else {
                                this.$message.error(res.data.msg);
                            }
                        })
                        .catch(err => {
                            console.error('删除图片失败', err);
                        });
                });
            },
            previewImage() {
                if (this.form.imageUrl) {
                    this.previewUrl = this.form.imageUrl;
                    this.isPreviewVisible = true;
                }
            },
            closePreview() {
                this.isPreviewVisible = false;
            },

            removeImage(){
                this.form.imageUrl = '';
                this.imageFile = null;
            },

            handleImageChange(file, fileList) {
                this.imageFile = file.raw;
                this.form.previewUrl  = window.URL.createObjectURL(file.raw);
            },
            selectParentNode(node, data) {
                this.form.parentId = data.categoryId;
                this.form.parentName = data.categoryName;
                if (data.categoryId === null || data.categoryId === undefined) {
                    this.form.parentName = '根目录';
                }
            },
            confirmParentSelection() {
                this.showTreeDialog = false;
            },
            handleNodeClick(node) {
                this.dialogType='edit';
                this.currentNode = node;
                this.buildBreadcrumb(node);
                this.showForm = true;
                this.loadFormData(node);
            },
            buildBreadcrumb(node) {
                this.breadcrumbList = [];
                let current = node;
                while (current && current.parentId !== 0) {
                    this.breadcrumbList.unshift(current.categoryName);
                    current = this.findParent(current.parentId);
                }
                if (current) {
                    this.breadcrumbList.unshift('根目录');
                }
            },
            filterNode(node, key) {
                if (node.categoryName.includes(key)) return true;
                if (node.children) {
                    const filteredChildren = node.children.filter(child => this.filterNode(child, key));
                    if (filteredChildren.length > 0) {
                        node.children = filteredChildren;
                        return true;
                    } else {
                        return false;
                    }
                }
                return false;
            },
            loadCategoryTree() {
                axios.get('/category')
                    .then(res => {
                        if (res.data.code === 20041) {
                            this.categoryTree = this.buildTree(res.data.data);
                        }
                    })
                    .catch(err => console.error('加载分类树失败', err));
            },
            buildTree(list) {
                const nodeMap = {};
                const tree = [];

                list.forEach(node => {
                    nodeMap[node.categoryId] = { ...node, children: [] };
                });

                list.forEach(node => {
                    const currentNode = nodeMap[node.categoryId];
                    const parentId = node.parentId;
                    if (parentId === null || parentId === undefined) {
                        tree.push(currentNode);
                    } else {
                        const parentNode = nodeMap[parentId];
                        if (parentNode) {
                            parentNode.children.push(currentNode);
                        } else {
                            console.warn('Parent node not found for node:', node.categoryId);
                        }
                    }
                });

                return tree;
            },
            loadParentTreeData() {
                axios.get('/category')
                    .then(res => {
                        if (res.data.code === 20041) {
                            this.parentTreeData = [{
                                categoryId: null,
                                categoryName: '根目录',
                                children: res.data.data.filter(node => node.parentId === null)
                            }];
                        }
                    });
            },
            openAddDialog() {
                this.dialogType = 'add';
                this.form.categoryId='';
                this.form.categoryName = '';
                this.form.sortOrder = 0;
                this.form.imageUrl = '';
                if (this.currentNode) {
                    this.form.parentId = this.currentNode.categoryId; // 确保这里获取到正确的 parentId
                    this.form.parentName = this.currentNode.categoryName;
                } else {
                    this.form.parentId = null; // 如果是根目录，parentId 为 null
                    this.form.parentName = '根目录';
                }
                this.showForm = true;
            },
            loadFormData(node) {
                this.form = {
                    categoryId: node.categoryId,
                    categoryName: node.categoryName,
                    parentId: node.parentId,
                    sortOrder: node.sortOrder || 0,
                    imageUrl: node.imageUrl || '',
                    parentName: this.findNodeName(this.categoryTree, node.parentId)
                };
            },
            findNodeName(nodes, targetId) {
                if (targetId === null || targetId === undefined) {
                    return '根目录';
                }
                for (let node of nodes) {
                    if (node.categoryId === targetId) return node.categoryName;
                    if (node.children && node.children.length > 0) {
                        const result = this.findNodeName(node.children, targetId);
                        // 关键修改：仅当 result 不是默认值时才返回
                        if (result && result !== '根目录') return result;
                    }
                }
                return '根目录';
            },
            findParent(id) {
                const find = (nodes) => {
                    for (let i = 0; i < nodes.length; i++) {
                        if (nodes[i].categoryId === id) {
                            return nodes[i];
                        }
                        if (nodes[i].children) {
                            const result = find(nodes[i].children);
                            if (result) {
                                return result;
                            }
                        }
                    }
                    return null;
                };
                return find(this.categoryTree);
            },
            handleSubmit() {
                this.$refs.form.validate(valid => {
                    if (valid) {
                        // 若图片未上传，先上传图片
                        if (!this.form.imageUrl && this.imageFile) {
                            const formData = new FormData();
                            formData.append('file', this.imageFile);

                            axios.post(this.ossUploadUrl, formData)
                                .then(res => {
                                    if (res.data.code === Code.SAVE_OK) {
                                        this.form.imageUrl = res.data.data;
                                        this.submitForm(); // 图片上传成功后再提交表单
                                    } else {
                                        this.$message.error('图片上传失败');
                                    }
                                });
                        } else {
                            this.submitForm(); // 图片已上传，直接提交表单
                        }
                    }
                });
            },

            submitForm() {
                console.log(this.form);
                const api = this.dialogType === 'add' ? '/category/add' : '/category';
                const method = this.dialogType === 'add' ? 'post' : 'put';


                const requestData = {
                    categoryId: this.form.categoryId,
                    categoryName: this.form.categoryName,
                    parentId: this.form.parentId,
                    sortOrder: this.form.sortOrder,
                    imageUrl: this.form.imageUrl // 若图片需单独处理，可能需要保留 FormData
                };
                axios({
                    method: method,
                    url: api,
                    data: requestData
                }).then(res => {
                    console.log(res);
                    if (res.data.code === 20031 || res.data.code === 20011) {
                        this.$message.success(`${this.dialogType === 'add' ? '新增' : '修改'}成功`);
                        this.showForm = false;
                        this.loadCategoryTree();
                    } else {
                        this.$message.error(res.data.msg);
                    }
                }).catch(err => {
                    console.error('操作失败', err);
                });
            },
            deleteCategory(categoryId) {
                this.$confirm('确认删除该分类？删除前请确保无子分类和关联商品', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    axios.delete(`/category/${categoryId}`)
                        .then(res => {
                            if (res.data.code === 20021) {
                                this.$message.success('删除成功');
                                this.showForm = false;
                                this.loadCategoryTree();
                            } else {
                                this.$message.error(res.data.msg);
                            }
                        });
                });
            },
            handleNodeDrop(draggingNode, dropNode, dropType) {
                console.log('Dragging node:', draggingNode);
                console.log('Drop node:', dropNode);
                console.log('Drop type:', dropType);
            }
        }
    });
</script>
</body>
</html>